"""
提示词管理器核心模块

提供提示词模板的管理、格式化和动态选择功能。
"""

from typing import Dict, List, Optional, Any, Tuple
from datetime import datetime

from .types import PromptTemplate, PromptStyle, PromptCategory, PromptUsageStats
from .templates import BuiltinTemplates
from .optimizer import PromptOptimizer, TemplateQualityMetrics


class PromptManager:
    """
    提示词管理器

    提供完整的提示词模板管理功能，包括：
    - 模板注册和管理
    - 动态格式化和验证
    - 智能模板推荐
    - 性能监控和优化
    """

    def __init__(self):
        """初始化提示词管理器"""
        self.templates: Dict[str, PromptTemplate] = {}
        self.current_style = PromptStyle.FRIENDLY
        self.optimizer = PromptOptimizer()
        self._load_builtin_templates()

    def _load_builtin_templates(self) -> None:
        """加载内置模板"""
        builtin_templates = BuiltinTemplates.get_all_templates()
        self.templates.update(builtin_templates)
        print(f"已加载 {len(builtin_templates)} 个内置提示词模板")

    def register_template(self, template: PromptTemplate, overwrite: bool = False) -> bool:
        """
        注册提示词模板

        Args:
            template: 要注册的模板
            overwrite: 是否覆盖同名模板

        Returns:
            bool: 注册是否成功
        """
        if template.name in self.templates and not overwrite:
            print(f"模板已存在，跳过注册: {template.name}")
            return False

        try:
            # 验证模板
            validation_issues = self.validate_template(template)
            if validation_issues:
                print(f"模板验证失败 {template.name}: {', '.join(validation_issues)}")
                return False

            self.templates[template.name] = template
            action = "覆盖" if overwrite else "注册"
            print(f"成功{action}模板: {template.name}")
            return True

        except Exception as e:
            print(f"注册模板失败 {template.name}: {e}")
            return False

    def get_template(self, template_name: str) -> Optional[PromptTemplate]:
        """
        获取指定的提示词模板

        Args:
            template_name: 模板名称

        Returns:
            Optional[PromptTemplate]: 提示词模板，不存在时返回None
        """
        return self.templates.get(template_name)

    def format_prompt(
        self,
        template_name: str,
        variables: Dict[str, Any],
        style: Optional[PromptStyle] = None,
        strict: bool = True
    ) -> str:
        """
        格式化提示词模板

        Args:
            template_name: 模板名称
            variables: 模板变量字典
            style: 指定风格，为None时使用当前风格
            strict: 是否严格模式（缺少变量时是否抛出异常）

        Returns:
            str: 格式化后的提示词

        Raises:
            ValueError: 模板不存在或缺少必需变量时抛出
        """
        template = self.get_template(template_name)
        if not template:
            raise ValueError(f"提示词模板不存在: {template_name}")

        # 风格检查
        target_style = style or self.current_style
        if template.style != target_style:
            # 可以在这里实现风格转换逻辑
            print(f"注意: 模板风格({template.style.value})与目标风格({target_style.value})不匹配")

        # 验证变量
        validation_issues = template.validate_variables(variables)
        if validation_issues and strict:
            raise ValueError(f"变量验证失败: {', '.join(validation_issues)}")

        # 格式化模板
        try:
            formatted_prompt = template.format(variables, strict=strict)

            # 记录使用情况
            self.optimizer.record_usage(template_name, len(formatted_prompt))

            return formatted_prompt
        except Exception as e:
            if strict:
                raise ValueError(f"模板格式化失败: {e}")
            # 非严格模式下，尝试简单替换
            return self._fallback_format(template, variables)

    def _fallback_format(self, template: PromptTemplate, variables: Dict[str, Any]) -> str:
        """降级格式化方法"""
        result = template.template
        for key, value in variables.items():
            result = result.replace(f"{{{key}}}", str(value))
        return result

    def format_prompt_with_context(
        self,
        template_name: str,
        context: str,
        question: str,
        additional_vars: Optional[Dict[str, Any]] = None
    ) -> str:
        """
        使用上下文和问题快速格式化RAG提示词

        Args:
            template_name: 模板名称
            context: 上下文信息
            question: 用户问题
            additional_vars: 额外变量

        Returns:
            str: 格式化后的提示词
        """
        variables = {
            "context": context,
            "question": question
        }

        if additional_vars:
            variables.update(additional_vars)

        return self.format_prompt(template_name, variables)

    def recommend_template(
        self,
        context_length: int = 0,
        category: Optional[PromptCategory] = None,
        style: Optional[PromptStyle] = None,
        complexity: str = "medium"
    ) -> Tuple[str, float, str]:
        """
        推荐最适合的模板

        Args:
            context_length: 上下文长度
            category: 期望的分类
            style: 期望的风格
            complexity: 复杂度偏好 ("low", "medium", "high")

        Returns:
            Tuple[str, float, str]: (模板名称, 得分, 推荐理由)
        """
        recommendation_context = {
            'context_length': context_length,
            'category': category,
            'preferred_style': style,
            'complexity': complexity
        }

        return self.optimizer.suggest_optimal_template(self.templates, recommendation_context)

    def auto_format(
        self,
        context: str,
        question: str,
        category: Optional[PromptCategory] = None,
        style: Optional[PromptStyle] = None
    ) -> Tuple[str, str]:
        """
        自动选择并格式化模板

        Args:
            context: 上下文信息
            question: 用户问题
            category: 期望的分类
            style: 期望的风格

        Returns:
            Tuple[str, str]: (格式化后的提示词, 使用的模板名称)
        """
        # 推荐模板
        template_name, score, reason = self.recommend_template(
            context_length=len(context),
            category=category or PromptCategory.RAG,
            style=style or self.current_style
        )

        print(f"推荐模板: {template_name} (得分: {score:.2f}, 理由: {reason})")

        # 格式化模板
        formatted_prompt = self.format_prompt_with_context(template_name, context, question)

        return formatted_prompt, template_name

    def set_style(self, style: PromptStyle) -> None:
        """
        设置默认提示词风格

        Args:
            style: 提示词风格
        """
        old_style = self.current_style
        self.current_style = style
        print(f"提示词风格已从 {old_style.value} 更改为 {style.value}")

    def get_style(self) -> PromptStyle:
        """获取当前默认风格"""
        return self.current_style

    def list_templates(
        self,
        category: Optional[PromptCategory] = None,
        style: Optional[PromptStyle] = None
    ) -> List[PromptTemplate]:
        """
        列出提示词模板

        Args:
            category: 按分类过滤
            style: 按风格过滤

        Returns:
            List[PromptTemplate]: 过滤后的模板列表
        """
        templates = list(self.templates.values())

        # 按分类过滤
        if category:
            templates = [
                t for t in templates
                if t.metadata and t.metadata.get("category") == category
            ]

        # 按风格过滤
        if style:
            templates = [t for t in templates if t.style == style]

        return templates

    def get_template_categories(self) -> List[PromptCategory]:
        """获取所有可用的模板分类"""
        categories = set()
        for template in self.templates.values():
            if template.metadata:
                category = template.metadata.get("category")
                if category:
                    categories.add(category)
        return list(categories)

    def get_template_styles(self) -> List[PromptStyle]:
        """获取所有可用的模板风格"""
        return list({template.style for template in self.templates.values()})

    def search_templates(self, keyword: str) -> List[PromptTemplate]:
        """
        搜索模板

        Args:
            keyword: 搜索关键词

        Returns:
            List[PromptTemplate]: 匹配的模板列表
        """
        keyword = keyword.lower()
        results = []

        for template in self.templates.values():
            # 在名称中搜索
            if keyword in template.name.lower():
                results.append(template)
                continue

            # 在描述中搜索
            if keyword in template.description.lower():
                results.append(template)
                continue

            # 在模板内容中搜索
            if keyword in template.template.lower():
                results.append(template)

        return results

    def validate_template(self, template: PromptTemplate) -> List[str]:
        """
        验证提示词模板

        Args:
            template: 要验证的模板

        Returns:
            List[str]: 验证问题列表，空列表表示验证通过
        """
        issues = []

        # 基本格式验证（已在PromptTemplate类中实现）
        try:
            # 检查必需变量
            if not template.required_vars:
                issues.append("模板没有定义必需变量")

            # 检查模板长度
            if len(template.template) > 5000:
                issues.append("模板过长，可能影响性能")

            # 检查变量命名
            for var in template.required_vars + template.optional_vars:
                if not var.isidentifier():
                    issues.append(f"变量名'{var}'不符合Python标识符规范")

        except Exception as e:
            issues.append(f"模板格式错误: {e}")

        return issues

    def analyze_template_quality(self, template_name: str) -> Optional[TemplateQualityMetrics]:
        """
        分析模板质量

        Args:
            template_name: 模板名称

        Returns:
            Optional[TemplateQualityMetrics]: 质量分析结果
        """
        template = self.get_template(template_name)
        if not template:
            return None

        return self.optimizer.analyze_template_quality(template)

    def get_optimization_suggestions(self) -> List[str]:
        """
        获取优化建议

        Returns:
            List[str]: 优化建议列表
        """
        suggestions = self.optimizer.generate_optimization_suggestions(self.templates)

        formatted_suggestions = []
        for suggestion in suggestions:
            formatted = f"[{suggestion.priority.upper()}] {suggestion.template_name}: {suggestion.description}"
            formatted_suggestions.append(formatted)

        return formatted_suggestions

    def get_usage_report(self) -> Dict[str, Any]:
        """获取使用情况报告"""
        performance_report = self.optimizer.get_performance_report()

        # 添加模板统计信息
        template_count = len(self.templates)
        style_counts = {}
        category_counts = {}

        for template in self.templates.values():
            # 风格统计
            style = template.style.value
            style_counts[style] = style_counts.get(style, 0) + 1

            # 分类统计
            if template.metadata:
                category = template.metadata.get("category")
                if category:
                    category_name = category.value if isinstance(category, PromptCategory) else str(category)
                    category_counts[category_name] = category_counts.get(category_name, 0) + 1

        return {
            "template_statistics": {
                "total_templates": template_count,
                "style_distribution": style_counts,
                "category_distribution": category_counts,
                "current_style": self.current_style.value
            },
            "performance_report": performance_report,
            "last_updated": datetime.now().isoformat()
        }

    def export_template(self, template_name: str) -> Optional[Dict[str, Any]]:
        """
        导出模板配置

        Args:
            template_name: 模板名称

        Returns:
            Optional[Dict[str, Any]]: 模板配置字典
        """
        template = self.get_template(template_name)
        if not template:
            return None

        return {
            "name": template.name,
            "template": template.template,
            "description": template.description,
            "style": template.style.value,
            "required_vars": template.required_vars,
            "optional_vars": template.optional_vars,
            "examples": template.examples,
            "metadata": template.metadata,
            "exported_at": datetime.now().isoformat()
        }

    def import_template(self, config: Dict[str, Any], overwrite: bool = False) -> bool:
        """
        导入模板配置

        Args:
            config: 模板配置字典
            overwrite: 是否覆盖同名模板

        Returns:
            bool: 导入是否成功
        """
        try:
            # 解析风格
            style_value = config.get("style", "friendly")
            style = PromptStyle(style_value)

            # 创建模板
            template = PromptTemplate(
                name=config["name"],
                template=config["template"],
                description=config.get("description", ""),
                style=style,
                required_vars=config.get("required_vars", []),
                optional_vars=config.get("optional_vars", []),
                examples=config.get("examples", []),
                metadata=config.get("metadata", {})
            )

            return self.register_template(template, overwrite)

        except Exception as e:
            print(f"导入模板失败: {e}")
            return False

    def __str__(self) -> str:
        """返回管理器信息的字符串表示"""
        report = self.get_usage_report()
        template_stats = report["template_statistics"]

        style_info = ", ".join([f"{style}: {count}" for style, count in template_stats["style_distribution"].items()])
        category_info = ", ".join([f"{cat}: {count}" for cat, count in template_stats["category_distribution"].items()])

        return f"""
=== 提示词管理器信息 ===
模板总数: {template_stats["total_templates"]}
当前风格: {template_stats["current_style"]}
风格分布: {style_info}
分类分布: {category_info}
支持功能: 模板管理、智能推荐、质量分析、性能监控
        """.strip()


# 全局提示词管理器实例
prompt_manager = PromptManager()